//判断函数，判断val是否是对象
const isObject = val => val!==null&&typeof val==='object';
//如果target还是obj就继续调用reactive函数
const convert = target => isObject(target)?reactive(target):target;
//判断是否有指定的属性
const hasOwnProperty = Object.prototype.hasOwnProperty
const hasOwn = (target, key) => hasOwnProperty.call(target, key);

export function reactive(target){
    //判断target

    if(!isObject(target)) return;
    // 处理器
    const handler = {
        get(target,key,receiver){
            //收集依赖
            track(target, key)
            const result = Reflect.get(target, key, receiver);
            //递归调用
            return convert(result)
        },
        set(target,key,value,receiver){

            const oldVal = Reflect.get(target, key, receiver);
            let result = true;
            //如果新旧值不同就重新赋值
            if(oldVal!==value){
                result = Reflect.set(target,key,value,receiver);
                //触发更新
                trigger(target, key)
            };
            return result;
        },
        deleteProperty(target,key){
            const hasKey = hasOwn(target, key)
            let result = Reflect.deleteProperty(target, key)
            if(hasKey &&  result){
                // 触发更新
                trigger(target, key)
            }
            return result
        }
    };
    return new Proxy(target,handler)
}

let activeEffect = null;
export function effect(callback){
    activeEffect = callback;
    callback()//访问响应式对象，收集依赖
    activeEffect = null;
}

let targetMap = new WeakMap();
export function track (target,key){
    if(!activeEffect) return;
    let depsMap = targetMap.get(target);
    if(!depsMap){
        targetMap.set(target,(depsMap = new Map()))
    }
    let dep = depsMap.get(key);
    if(!dep){
        depsMap.set(key,(dep = new Set()))
    }
    dep.add(activeEffect)
}

export function trigger(target,key){
    const depsMap = targetMap.get(target);
    if(!depsMap) return;
    let dep = depsMap.get(key);
    if(dep){
        dep.forEach( effect => {
            effect();
        });
    }
}

export function ref(raw){
    //判断是否是ref创建的对象，如果是直接返回
    if(isObject(raw) && raw.__v_isRef){
        return;
    }
    let value = convert(raw);
    const r = {
        __v_isRef:true,
        get value (){
            track(r,'value');
            return value;
        },
        set value (newValue){
            if(newValue!==value){
                raw = newValue;
                value = convert(raw);
                trigger(r,'value')
            }
        }
    };
    return r;
}

export function toRefs(proxy){
    const ret = proxy instanceof Array ? new Array(proxy.length):{};
    for (const key in proxy) {
        ret[key] = toProxyRef(proxy,key)
    }
    return ret
}

function toProxyRef (proxy, key) {
    const r = {
      __v_isRef: true,
      get value () {
        return proxy[key]
      },
      set value (newValue) {
        proxy[key] = newValue
      }
    }
    return r
}
export function computed (getter) {
    const result = ref()
    effect(() => (result.value = getter()))
    return result
}